<?php
class ClsNaanalDBTable
{
    /**
     * stores a copy of arrRecord for future reference
     * @var array
     */
    private $arrRecordOriginal=array();
    /**
     * store the query result in two dimensional associative array
     * @var array
     */
    private $arrRecord=array();
    /**
     * hold new record index to insert into table
     * @var array
     */
    private $arrNewRecordIndex=array();
    /**
     * hold modified record index to update into table
     * @var array
     */
    private $recordCount=0;
    private $arrUpdateRecordIndex=array();
    private $arrField=array();
    private $emptyRecord=array();
    private $arrWhere=array();
    private $table="";
    private $objPDO=null;
    
    private $arrUniqueRecordField=array();
    
    /**
     * delete those records which is not updated. useful for tables which hold only updated records. 
     * @var boolean
     */
    private $useUpdatedRecordsOnly=false;
    
    private $arrError=array();
    
    public function __construct($table,$arrWhere,&$objPDO)
    {
        $this->objPDO=$objPDO;
        $this->arrWhere=$arrWhere;
        $this->table=$table;
    }
    public function setUseUpdatedRecordsOnly($use)
    {
        $this->useUpdatedRecordsOnly=$use;
    }
    public static function &getInstance($table,$arrWhere,&$objPDO)
    {
        $obj=new ClsNaanalDBTable($table,$arrWhere,$objPDO);
        return $obj;
    }
    /**
     * An array of field used for idendifying the unique record
     * @param AssociativeArray $arrRowKeyData
     */
    public function load($arrUniqueRecordField,$arrField)
    {
        $this->arrUniqueRecordField=$arrUniqueRecordField;
        $this->arrField=$arrField;
        foreach($this->arrField as $fieldIndex=>$tmpfld)
        {
            $this->emptyRecord[$fieldIndex]="";
        }
        $objSql=new ClsSQL();
        //$objSql->addField("id");
        if($arrField)
        foreach($arrField as $field)
        {
            $objSql->addField($field);
        }
        $objSql->addTable($this->table);
        if($this->arrWhere) $objSql->addWhereAsArray($this->arrWhere);
        $sql=$objSql->render();
        $this->objPDO->setQuery($sql);
        $this->arrRecord = $this->objPDO->getAllRow();
        $this->arrRecordOriginal=$this->arrRecord;
        $this->recordCount=count($this->arrRecord);
    }
    
    public function findRecordIndex($arrUniqueRecordData)
    {
        if($this->arrRecord)
        foreach($this->arrRecord as $ind=>$row)
        {
            $isMatch=true;
            foreach($this->arrUniqueRecordField as $field)
            {
                $fieldIndex=array_search($field, $this->arrField);
                if($row[$fieldIndex]!=$arrUniqueRecordData[$field])
                {
                    $isMatch=false;
                    break;
                }
            }
            if($isMatch) return $ind;
        }
        return -1;
    }
    
    public function setData($arrUniqueRecordData,$columnField,$data)
    {
        $index=$this->findRecordIndex($arrUniqueRecordData);
        if($index>-1)
        {
            $this->arrRecord[$index][$columnField]=$data;
            if(!in_array($needle, $this->arrUpdateRecordIndex))
            {
                $this->arrUpdateRecordIndex[]=$index;
            }
            return true;
        }
        return false;
    }
    
    public function insertEmptyRecord()
    {
        $this->arrRecord[$this->recordCount]=$this->emptyRecord;
        $this->arrNewRecordIndex[]=$this->recordCount;
        return $this->recordCount;
    }
    
    public function addRecord($arrField)
    {
        $index=$this->insertEmptyRecord();
        $this->recordCount=$this->recordCount+1;
        foreach($this->arrRecord[$index] as $fieldIndex=>$data)
        {
            $this->arrRecord[$index][$fieldIndex]=$arrField[$this->arrField[$fieldIndex]];
        }
        return true;
    }
    
    public function modifyRecord($arrField)
    {
        $arrUniqueRecordData=array();
        foreach($this->arrUniqueRecordField as $field)
        {
            $arrUniqueRecordData[$field]=$arrField[$field];
        }
        $index=$this->findRecordIndex($arrUniqueRecordData);
        if($index>-1)
        {
            foreach($this->arrRecord[$index] as $fieldIndex=>$data)
            {
                $this->arrRecord[$index][$fieldIndex]=$arrField[$this->arrField[$fieldIndex]];
            }
            $this->arrUpdateRecordIndex[]=$index;
            return true;
        }
        return false;
    }
    
    public function updateRecord($arrField)
    {
        if(!$this->modifyRecord($arrField))
        {
            if(!$this->addRecord($arrField))
            {
                return false;
            }
        }
        return true;
    }
    
    public function setDataByIndex($index,$field,$data)
    {
        $this->arrRecord[$index][$field]=$data;
        if(!in_array($index, $this->arrNewRecordIndex))
        {
            if(!in_array($needle, $this->arrUpdateRecordIndex))
            {
                $this->arrUpdateRecordIndex[]=$index;
            }
        }
    }
    
    public function update()
    {
        if($this->arrRecord)
        foreach($this->arrRecord as $index=>$row)
        {
            /**
             * if the record has to update, update it.
             * if $this->useUpdatedRecordsOnly is true, delete the remaining records. else ignore it
             * $this->useUpdatedRecordsOnly = true - used for mass update all records at a time. the database should have only the records in the object
             * $this->useUpdatedRecordsOnly = false - used for mass update few records.
             */
            if(in_array($index, $this->arrUpdateRecordIndex))
            {
                $objWrapper =  ClsWrapper::getInstance($this->table);
                $arrUniqueRecordData=array();
                foreach($this->arrUniqueRecordField as $field)
                {
                    $fieldIndex=  array_search($field, $this->arrField);
                    $arrUniqueRecordData[$field]=$row[$fieldIndex];
                }
                foreach($this->arrWhere as $where)
                {
                    $fieldIndex=  array_search($where["field"], $this->arrField);
                    $arrUniqueRecordData[$where["field"]]=$row[$fieldIndex];
                }
                foreach($this->arrField as $field)
                {
                    $set="set_{$field}";
                    $fieldIndex=  array_search($field, $this->arrField);
                    $objWrapper->$set($row[$fieldIndex]);
                }
                $objWrapper->update($arrUniqueRecordData);
            }
            else if(in_array($index, $this->arrNewRecordIndex))
            {
                $objWrapper =  ClsWrapper::getInstance($this->table);
                foreach($this->arrField as $colindex=>$field)
                {
                    if($field=="id") continue;
                    $set="set_{$field}";
                    $fieldIndex=  array_search($field, $this->arrField);
                    $objWrapper->$set($row[$fieldIndex]);
                }
                $objWrapper->update();
            }
            else
            {
                if($this->useUpdatedRecordsOnly)
                {
                    $objSql=new ClsSQL("DELETE");
                    $objSql->addTable($this->table);
                    $arrUniqueRecordData=array();
                    foreach($this->arrUniqueRecordField as $field)
                    {
                        $fieldIndex=  array_search($field, $this->arrField);
                        $objSql->addWhere($field, $row[$fieldIndex]);
                    }
                    foreach($this->arrWhere as $where)
                    {
                        $fieldIndex=  array_search($where["field"], $this->arrField);
                        $objSql->addWhere($where["field"], $row[$fieldIndex]);
                    }
                    $sql=$objSql->render();
                    $this->objPDO->setQuery($sql);
                }
            }
        }
    }
}
?>